package com.Webserver.core;

import com.Webserver.core.annotations.Controller;
import com.Webserver.core.annotations.RequestMapping;

import javax.swing.plaf.synth.SynthOptionPaneUI;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

/**
 * 该类用于维护请求路径与对应的业务处理类和方法
 */
public class HandlerMapping {
    /**
     * 保存每个请求路径与对应的业务处理方法
     * key:请求路径
     * value:处理该请求的业务方法
     *
     * 例如:
     *
     * key:/myweb/reg
     *
     * value:MethodMapping{
     *     Object Controller => UserController的实例
     *     Method method => reg方法
     *    }
     */
    private static Map<String,MethodMapping> mapping = new HashMap<>();

    static {
        try {
            initMapping();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }
    private static void initMapping() throws ClassNotFoundException, IllegalAccessException, InstantiationException, URISyntaxException {
        /**
         * 1:扫描com.webserver.controller包下的所有类.
         * 2:利用反射机制加载这些类的类对象.
         * 3:判断该类是否使用注解@Controller标注，没有的则忽略.
         *      实例化当前Collection备用(第5步用)
         * 4:扫描该类中所有的方法，并判断方法是否使用注解@RequestMapping标注，没有的忽略.
         * 5:将RequestMapping中的获取参数到(该方法对应的请求路径)并作为key,
         *   将第三步创建的Controller实例和当前方法对象(Method对象)组成一个MethodMapping作为value,
         *   存入到mapping这个Map.
         */
        File file = new File(HandlerMapping.class.getClassLoader().getResource("./com/Webserver/controller").toURI());
        File[] files = file.listFiles(f->f.getName().endsWith(".class"));
        for(File file1 : files) {
            String str = file1.getName();
            String className = str.substring(0,str.lastIndexOf("."));
            Class cls = Class.forName("com.Webserver.controller."+className);
            if (cls.isAnnotationPresent(Controller.class)) {
                Object obj = cls.newInstance();//com.Webserver.core.HandlerMapping$MethodMapping@723279cf
//                Class obj = Controller.class;//com.Webserver.core.HandlerMapping$MethodMapping@723279cf
                Method[] method = cls.getDeclaredMethods();
                for (Method methods : method) {
                    if (methods.isAnnotationPresent(RequestMapping.class)) {
                        RequestMapping rm = methods.getAnnotation(RequestMapping.class);
                        String key = rm.value();
                        MethodMapping value = new MethodMapping(obj,methods);
                        mapping.put(key,value);
                    }
                }
            }
        }
        System.out.println(mapping);
    }

    /**
     * 根据给定的请求路径获取处理该路径的业务方法
     * @param path
     * @return
     */
    public static MethodMapping getMethod(String path){
        return mapping.get(path);
    }

    /**
     * 当前类的每一个实例用于记录一个业务方法以及该方法所属的Controller对象
     */
    public static class MethodMapping{
        private Object controller;//key:对应的网址"/myweb/writeArticle"
        private Method method;//value:网址对应的业务

        public MethodMapping(Object controller, Method method) {
            this.controller = controller;
            this.method = method;
        }

        public Object getController() {
            return controller;
        }

        public void setController(Object controller) {
            this.controller = controller;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }
    }

    public static void main(String[] args) {

    }
}
